<template>
  <el-popover placement="top-start" title="换肤" width="200" trigger="hover">
    <p>点击取色板可更换主题,重置将恢复系统默认主题</p>
    <div style="text-align: right; margin: 0">
      <el-button @click="resetTheme()" type="primary" size="mini">重置</el-button>
    </div>
    <!-- <el-tooltip slot="reference" content="更换主题" effect="dark" placement="bottom"> -->
    <el-color-picker slot="reference" v-model="theme" class="theme-picker" popper-class="theme-picker-dropdown" />
    <!-- </el-tooltip> -->
  </el-popover>

</template>

<script>
const version = require("element-ui/package.json").version; // 引入查看版本

export default {
  data() {
    return {
      chalk: "",
      ORIGINAL_THEME: "#409EFF", // 默认主题色
      theme: "#409EFF" //默认主题色
    };
  },
  created() {
    this.initTheme();
  },
  watch: {
    theme(val, oldVal) {
      if (typeof val !== "string") return;
      if (!val) {
        return;
      }
      const themeCluster = this.getThemeCluster(val.replace("#", ""));
      const originalCluster = this.getThemeCluster(oldVal.replace("#", ""));
      const getHandler = (variable, id) => {
        return () => {
          const originalCluster = this.getThemeCluster(
            this.ORIGINAL_THEME.replace("#", "")
          );
          const newStyle = this.updateStyle(
            this[variable],
            originalCluster,
            themeCluster
          );

          let styleTag = document.getElementById(id);
          if (!styleTag) {
            styleTag = document.createElement("style");
            styleTag.setAttribute("id", id);
            document.head.appendChild(styleTag);
          }
          styleTag.innerText = newStyle;
        };
      };

      const chalkHandler = getHandler("chalk", "chalk-style");

      if (!this.chalk) {
        const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`;
        this.getCSSString(url, chalkHandler, "chalk");
      } else {
        chalkHandler();
      }

      const styles = [].slice
        .call(document.querySelectorAll("style"))
        .filter(style => {
          const text = style.innerText;
          return (
            new RegExp(oldVal, "i").test(text) && !/Chalk Variables/.test(text)
          );
        });
      styles.forEach(style => {
        const { innerText } = style;
        if (typeof innerText !== "string") return;
        style.innerText = this.updateStyle(
          innerText,
          originalCluster,
          themeCluster
        );
      });

      try {
        //方便以后开发没有用vuex好定位问题
        if (val) {
          this.$store.state.publicVariable.theme.activeTextColor = val;
          localStorage.setItem("theme", val);
        }
      } catch (error) {
        this.$message.error("主题色值异常错误");
      }
    }
  },

  methods: {
    // 初始化主题颜色
    initTheme() {
      if (localStorage.getItem("theme")) {
        this.$store.state.publicVariable.theme.activeTextColor = localStorage.getItem(
          "theme"
        );
      }
      this.theme =
        this.$store.state.publicVariable.theme.activeTextColor || "#00B2A9";
    },
    //重置主题色
    async resetTheme() {
      if (await this.$confirm("此操作将恢复系统默认主题")) {
        this.theme = "#00B2A9";
      }
    },
    updateStyle(style, oldCluster, newCluster) {
      let newStyle = style;
      oldCluster.forEach((color, index) => {
        newStyle = newStyle.replace(new RegExp(color, "ig"), newCluster[index]);
      });
      return newStyle;
    },

    getCSSString(url, callback, variable) {
      const xhr = new XMLHttpRequest();
      xhr.onreadystatechange = () => {
        if (xhr.readyState === 4 && xhr.status === 200) {
          this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, "");
          callback();
        }
      };
      xhr.open("GET", url);
      xhr.send();
    },

    getThemeCluster(theme) {
      const tintColor = (color, tint) => {
        let red = parseInt(color.slice(0, 2), 16);
        let green = parseInt(color.slice(2, 4), 16);
        let blue = parseInt(color.slice(4, 6), 16);

        if (tint === 0) {
          // when primary color is in its rgb space
          return [red, green, blue].join(",");
        } else {
          red += Math.round(tint * (255 - red));
          green += Math.round(tint * (255 - green));
          blue += Math.round(tint * (255 - blue));

          red = red.toString(16);
          green = green.toString(16);
          blue = blue.toString(16);

          return `#${red}${green}${blue}`;
        }
      };

      const shadeColor = (color, shade) => {
        let red = parseInt(color.slice(0, 2), 16);
        let green = parseInt(color.slice(2, 4), 16);
        let blue = parseInt(color.slice(4, 6), 16);

        red = Math.round((1 - shade) * red);
        green = Math.round((1 - shade) * green);
        blue = Math.round((1 - shade) * blue);

        red = red.toString(16);
        green = green.toString(16);
        blue = blue.toString(16);

        return `#${red}${green}${blue}`;
      };

      const clusters = [theme];
      for (let i = 0; i <= 9; i++) {
        clusters.push(tintColor(theme, Number((i / 10).toFixed(2))));
      }
      clusters.push(shadeColor(theme, 0.1));
      return clusters;
    }
  }
};
</script>

<style scoped>
.theme-picker .el-color-picker__trigger {
  vertical-align: middle;
}

.theme-picker-dropdown .el-color-dropdown__link-btn {
  display: none;
}
</style>
